<script>
import ConditionConfig from "./index.vue";

export default {
  name: "conditionTree",
  components: {ConditionConfig},
  props: {
    showExpression: {
      type: Boolean,
      default: () => true
    }
  },
  data() {
    return {
      comKey: "abc",
      condition: [
        {id: "a1", parentId: null, type: "condition", level: 1, attribute: "name", symbol: ">", value: "1"},
        {id: "a2", parentId: null, type: "connector", level: 1, connector: "AND"},
        {id: "a3", parentId: null, type: "condition", level: 1, attribute: "age", symbol: "<", value: "2"},
        {id: "a4", parentId: null, type: "connector", level: 1, connector: "OR"},
        {id: "a5", parentId: null, type: "condition", level: 1, attribute: "sex", symbol: "==", value: "3"},
        {id: "a6", parentId: null, type: "connector", level: 1, connector: "AND"},
        {
          id: "a7", parentId: null, type: "conditionGroup", level: 1, children: [
            {id: "a8", parentId: "a7", type: "condition", level: 2, attribute: "age", symbol: "!=", value: "4"},
            {id: "a9", parentId: "a7", type: "connector", level: 2, connector: "OR"},
            {id: "a10", parentId: "a7", type: "condition", level: 2, attribute: "sex", symbol: "in", value: "5"},
          ]
        },
      ],
      maxLevel: 3,

      expression: "",
    }
  },
  methods: {
    //生成表达式
    initExpression() {
      let expression = "";
      let loopCondition = (data, T) => {
        if (data && data.length > 0) {
          if (T === "group") {
            expression += "( "
          }
          for (let i = 0; i < data.length; i++) {
            let item = data[i];
            if (item.type === "condition") {
              expression += item.attribute + ' ' + item.symbol + ' ' + item.value + ' '
            }
            if (item.type === "connector") {
              // str += (item.connector === "AND" ? "&&" : "||") + ' '
              expression += item.connector + ' '
            }
            if (item.type === "conditionGroup") {
              loopCondition(item.children, "group")
            }
          }
          if (T === "group") {
            expression += " ) "
          }
        }
      }
      loopCondition(this.condition)

      this.expression = expression;

      return expression;
    },
    /**
     * 如果一级目录删除完毕后 二级将自动层级上移
     * */
    setLastGroup() {
      if (this.condition.length === 1 && this.condition[0].type === "conditionGroup") {
        let data = JSON.parse(JSON.stringify(this.condition));
        this.condition = [];
        data[0].children.forEach(item => {
          this.condition.push({...item, parentId: null, level: 1})
        })
      }

      this.setTreeLevel(this.condition);
    },
    //遍历设置树形层级
    setTreeLevel(nodes, level = 1) {
      nodes.forEach(node => {
        node.level = level; // 设置当前节点的层级
        this.maxLevel = level;
        if (node.children) {
          this.setTreeLevel(node.children, level + 1); // 递归设置子节点的层级
        }
      });
    },
    /**
     * @param type 操作类型
     * @param row 当前操作行
     * @param parentNode 当前操作行的父级
     * @param condition 当前操作行所处的list
     * @param before 当前操作行的上一行数据
     * @param after 当前操作行的下一行数据
     * @param parentNodeBefore 当前操作行 父类的上一行数据
     * @param parentNodeAfter 当前操作行 父类的下一行数据
     *
     * 如果有父级（parentNode 不为空）就证明当前行在分组中
     * 如果有上一行（before parentNodeBefore 不为空）证明当前行不是第一行
     * 如果有下一行（after parentNodeAfter 不为空）证明当前行不在最后一行
     * */
    nodeClick(type, row, parentNode, condition, before, after, parentNodeBefore, parentNodeAfter) {
      this[type]({row, parentNode, condition, before, after, parentNodeBefore, parentNodeAfter})

      this.comKey = this.getOnlyId();
    },

    /**
     * @param tree 树形数据
     * @param nodeId 删除树形中指定id的数据
     * */
    deleteAssignNode(tree, nodeId) {
      for (let i = 0; i < tree.length; i++) {
        if (tree[i].id === nodeId) {
          tree.splice(i, 1);
          return;
        } else if (tree[i].children && tree[i].children.length > 0) {
          this.deleteAssignNode(tree[i].children, nodeId);
        }
      }
    },

    //删除单行数据
    deleteNode(arg) {
      let {row, parentNode, condition, before, after, parentNodeBefore, parentNodeAfter} = arg;
      //如果没有父级，证明当前行数据为一级目录
      if (Object.keys(parentNode).length === 0) {
        //如果当前行 前一行没有数据 那就需要删除当前行的下一行
        let connector = !!before ? before : !!after ? after : undefined;
        //如果有before或者after就执行删除连接符，如果没有就直接删除操作行数据
        if (connector) this.deleteAssignNode(condition, connector.id);
        this.deleteAssignNode(condition, row.id);
      } else {
        //如果当前分组条件和连接符的总长度为3，证明条件有2个
        let nextChildren = [];
        if (condition.length === 3) {
          condition.forEach(({type, children}) => {
            if (type === "conditionGroup" && children && children.length > 0) {
              children.forEach(item => {
                nextChildren.push({...item, level: item.level - 1, parentId: parentNode.id})
              })
            }
          })
          if (nextChildren.length > 0) {
            parentNode.children = nextChildren;
          } else {
            //如果当前行 前一行没有数据 那就需要删除当前行的下一行
            let connector = !!before ? before : !!after ? after : undefined;
            //如果有before或者after就执行删除连接符，如果没有就直接删除操作行数据
            if (connector) this.deleteAssignNode(condition, connector.id);
            this.deleteAssignNode(condition, row.id);
          }
        } else if (condition.length === 1) {
          //如果当前行 前一行没有数据 那就需要删除当前行的下一行
          let connector = Object.keys(parentNodeBefore).length > 0 ? parentNodeBefore : Object.keys(parentNodeAfter).length > 0 ? parentNodeAfter : undefined;
          //如果有before或者after就执行删除连接符，如果没有就直接删除操作行数据
          if (connector) this.deleteAssignNode(this.condition, connector.id);
          this.deleteAssignNode(this.condition, parentNode.id);
        } else {
          //如果当前行 前一行没有数据 那就需要删除当前行的下一行
          let connector = !!before ? before : !!after ? after : undefined;
          //如果有before或者after就执行删除连接符，如果没有就直接删除操作行数据
          if (connector) this.deleteAssignNode(condition, connector.id);
          this.deleteAssignNode(condition, row.id);
        }
      }
      this.setLastGroup();
    },
    //添加一行数据
    addCondition(arg) {
      let {row, condition, after} = arg;
      let index = condition.map(i => i.id).indexOf(row.id);

      condition.splice(index + 2, 0, {
        id: this.getOnlyId(), parentId: row.parentId, type: "condition", level: row.level,
        attribute: "", symbol: "", value: ""
      })
      if (after && Object.keys(after).length > 0) {
        condition.splice(index + 3, 0, {
          id: this.getOnlyId(), parentId: row.parentId, type: "connector", level: row.level, connector: "AND"
        })
      } else {
        condition.splice(index + 1, 0, {
          id: this.getOnlyId(), parentId: row.parentId, type: "connector", level: row.level, connector: "AND"
        })
      }

      this.setTreeLevel(this.condition);
    },
    //添加一组数据数据
    addConditionGroup(arg) {
      let {row, condition, after} = arg;
      let index = condition.map(i => i.id).indexOf(row.id);
      let pId = this.getOnlyId()
      let group = {
        id: pId, parentId: row.parentId, type: "conditionGroup", level: row.level, children: [
          {
            id: this.getOnlyId(),
            parentId: pId,
            type: "condition",
            level: row.level + 1,
            attribute: "",
            symbol: "",
            value: ""
          },
          {
            id: this.getOnlyId(),
            parentId: pId,
            type: "connector",
            level: row.level + 1,
            connector: "AND"
          },
          {
            id: this.getOnlyId(),
            parentId: pId,
            type: "condition",
            level: row.level + 1,
            attribute: "",
            symbol: "",
            value: ""
          },
        ]
      }
      condition.splice(index + 2, 0, group)
      if (after && Object.keys(after).length > 0) {
        condition.splice(index + 3, 0, {
          id: this.getOnlyId(), parentId: row.parentId, type: "connector", level: row.level, connector: "AND"
        })
      } else {
        condition.splice(index + 1, 0, {
          id: this.getOnlyId(), parentId: row.parentId, type: "connector", level: row.level, connector: "AND"
        })
      }

      this.setTreeLevel(this.condition);
    },
    /**
     * 生成唯一id
     * len 机器码有多少位
     * */
    getOnlyId(len = 13) {
      let date = (new Date()).valueOf();//获取时间戳
      let txt = '1234567890';//生成的随机机器码
      let pwd = '';//定义空变量用来接收机器码
      for (let i = 0; i < len; i++) {
        pwd += txt.charAt(Math.floor(Math.random() * txt.length));//循环机器码位数随机填充
      }
      return date + pwd;//相加生成唯一ID
    }
  }
}
</script>

<template>
  <div class="condition-temp">
    <template v-if="showExpression">
      <el-button type="primary" size="mini" @click="initExpression">生成表达式</el-button>
      <p>{{ expression }}</p>
    </template>

    <div class="condition-temp-con">
      <condition-config :key="comKey"
                        :condition="condition"
                        @nodeClick="nodeClick"
                        :maxLevel="maxLevel">
        <template slot="rowContent" slot-scope="{row}">
          <el-select style="width: 140px;" size="mini" v-model="row.attribute" placeholder="请选择">
            <el-option label="姓名" value="name"></el-option>
            <el-option label="年龄" value="age"></el-option>
            <el-option label="性别" value="sex"></el-option>
          </el-select>
          &nbsp;
          <el-select style="width: 100px" size="mini" v-model="row.symbol" placeholder="请选择">
            <el-option label="==" value="=="></el-option>
            <el-option label="!=" value="!="></el-option>
            <el-option label=">" value=">"></el-option>
            <el-option label="<" value="<"></el-option>
            <el-option label=">=" value=">="></el-option>
            <el-option label="<=" value="<="></el-option>
            <el-option label="IN" value="IN"></el-option>
            <el-option label="NOTIN" value="NOTIN"></el-option>
            <el-option label="LIKE" value="LIKE"></el-option>
          </el-select>
          &nbsp;
          <el-input style="width: 140px;" placeholder="请输入" size="mini" v-model="row.value"></el-input>
        </template>
      </condition-config>
    </div>
  </div>
</template>

<style scoped lang="scss">
.condition-temp {
  width: 100%;

  .condition-temp-con {
    width: 100%;
    height: 100%;
    overflow: auto;
    padding: 10px 20px 10px 40px;
    box-sizing: border-box;
  }
}
</style>
